<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.1 / SVN信息: $Id: class.JCAT_Package.php 1539 2009-03-26 06:55:07Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

include_once dirname(__FILE__).'/SOAP/interface.JCAT_ISSMI.php' ;


/**
 * 包管理类,这是一个静态类
 *
 * @author		alee
 * @access		public
 */
class JCAT_Package implements JCAT_ISSMI
{
	/**
	 * 导入整个包
	 * 
	 * @access	public
	 * @param	$sPackage							string		被导入的包的路径 或  包的ID(JCAT类中的一个常量)，
	 * @param	$bForceRefreshCache=fasle			bool		强制重建 Classes Path 文件
	 * @static
	 * @return	void
	 */
	static public function Import( $sPackage, $bForceRefreshCache=false ) 
	{
		// 检查路径
		if( !is_dir($sPackage) )
		{
			throw new JCAT_Exception("Package:'{$sPackage}' does not exists.",JCAT_Exception::MakeExceptionCode(__CLASS__,1)) ;
		}
		$sPackagePath = realpath($sPackage).'/' ;
		
		// 创建 Classes Path 文件
		$sClassesPathFile = $sPackagePath.self::$sClassesPathFilename ;
		if( JCAT_ProjectState::Get(JCAT_ProjectState::ALWAYS_RECREATE_CLASSESPATH)
				or $bForceRefreshCache
				or !is_file($sClassesPathFile) )
		{
		
			// 类路径 文件
			if( !is_file($sClassesPathFile) )
			{
				if( $hFile=fopen($sClassesPathFile,'a') )
				{
					fclose($hFile);
					chmod($sClassesPathFile,0666) ;
				}
				else
				{
					return false ;
				}
			}
			
			
			$arrFileLines = array('<?') ;

			// 扫描类
			$arrClassesPath = self::ScanClass($sPackagePath) ;
			foreach ($arrClassesPath as $arrMapping)
			{
				$arrFileLines[] = __CLASS__."::RegisterClass('{$arrMapping['class']}',\$sDirectoryBase.'{$arrMapping['file']}') ;" ;
			}
			
			$arrFileLines[] = '?>' ;
			$sFileContents = implode("\r\n",$arrFileLines) ;
			
			// 写入文件
			if( !file_put_contents($sClassesPathFile,$sFileContents) )
			{
				throw new JCAT_Exception(
					JCAT_Language::SentenceEx('请确保拥有权限，无法创建 Classes Path 文件：%s','JCAT',null,$sClassesPathFile)
					, __macro_exception_code__
				) ;
			}
		}
		
		// 读取 Classes Path 文件
		$sDirectoryBase = $sPackagePath ;		// <<--- 在 $sClassesPathFile 文件中用到的变亮
		require_once $sClassesPathFile ; 
	}


	/**
	 * 导入一个类
	 *  
	 *
	 * @access	public
	 * @param	$sClass					string			类名或类文件完整路径
	 * @param	$PathOrPackageID=null	string,int		类文件的路径 或 所在包的ID
	 * @static
	 * @return	void
	 */
	static public function ImportClass(  $sClass, $PathOrPackageID=null ) 
	{
		// 类已经导入
		if( self::ClassExists($sClass) )
		{
			return ;
		}
			
		// 指定文件
		if( is_file($sClass) )
		{
			require_once ($sClass) ;
			return ;
		}
		
		// 提供类名
		else
		{
			JCAT_ASSERT::ASSERT_ISTHESE($PathOrPackageID,array('string','int'));

			// 参数 $PathOrPackageID 为路径
			if( is_string($PathOrPackageID) )
			{
				$sClassPath = $PathOrPackageID ;
			}
			
			// 参数 $PathOrPackageID 为 包ID
			else if( is_int($PathOrPackageID) )
			{
				$sClassPath = self::GetPackagePath($PathOrPackageID) ;
			}
			
			else 
			{
				JCAT_ASSERT::ASSERT_(0,'!?') ;
			}
			
			// 在目录中依据 JCAT 命名规则 寻找 class 文件
			if(is_dir($sClassPath))
			{
				$sClassPath = self::FindClassFileByNamingRule($sClass,$sClassPath) ;

				if($sClassPath===false)
				{
					JCAT_ASSERT::ASSERT_(0,"Coundn`t found class {$sClass}`s file and imported it. ",JCAT_Exception::MakeExceptionCode(__CLASS__,2)) ;
				}
			}

			// 载入
			require $sClassPath ;
			
		}
		
	}



	/**
	 * 导入一个接口
	 * 
	 * @access	public
	 * @param	$sInterface		string	类名或类文件完整路径
	 * @param	$nPackage=null	int		类所在的包
	 * @static
	 * @return	void
	 */
	static public function ImportInterface(  $sInterface, $nPackage=null ) 
	{
		// 指定文件
		if( is_file($sInterface) )
		{
			require_once ($sInterface) ;
			return ;
		}
		
		// 
		else
		{
			// 类已经导入
			if( self::ClassExists($sInterface,true) )
				return ;
			
			// 包 所在目录
			$sPackage = self::GetPackagePath($nPackage) ;
			
			// 按照命名规则寻找类文件
			$sPath = self::FindClassFileByNamingRule($sInterface,$sPackage,self::$arrInterfaceFilePatterns) ;
			if($sPath===false)
				throw new JCAT_Exception("Coundn`t found interface {$sInterface}`s file and imported it. ",JCAT_Exception::MakeExceptionCode(__CLASS__,3)) ;
			
			// 载入
			require $sPath ;
		}
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$Methods='*'		string,array	被导入的静态方法，可以是 数组（多个方法的名称），字串（指定的方法名称），和'*'（所有的静态方法）
	 * @param	$sClass				string			类名
	 * @param	$PackageOrClassFile	int,string		类所属包的ID 或 类文件的完整路径
	 * @return	int
	 */
	static public function ImportStaticMethod(  $Methods='*', $sClass, $PackageOrClassFile ) 
	{
		// $PackageOrClassFile  包ID
		if( is_int($PackageOrClassFile) )
		{
			$sPackagePath = self::GetPackagePath($PackageOrClassFile) ;
			if( empty($sPackagePath) )
				throw new JCAT_Exception("无效的 包ID：$nPackage ",JCAT_Exception::MakeExceptionCode(__CLASS__,4)) ;
			
			// 找到类文件
			$sClassPath = self::FindClassFileByNamingRule($sClass,$sPackagePath) ;
			if( $sClassPath===false )
				throw new JCAT_Exception("无法根据 JCAT的文件命名规则找到类:{$sClass} 的文件 ",JCAT_Exception::MakeExceptionCode(__CLASS__,5)) ;
		}
		
		// $PackageOrClassFile  类文件的完整路径
		else if( is_string($PackageOrClassFile) )
		{
			if( !is_file($PackageOrClassFile) )
				throw new JCAT_Exception("参数\$PackageOrClassFile 必须为 有效的包ID(int) 或 一个存在的类文件(string)。",JCAT_Exception::MakeExceptionCode(__CLASS__,8)) ;
			$sClassPath = $PackageOrClassFile ;
		}
		
		// $PackageOrClassFile 参数无效
		else
			throw new JCAT_Exception("参数\$PackageOrClassFile 必须为 有效的包ID(int) 或 一个存在的类文件(string)",JCAT_Exception::MakeExceptionCode(__CLASS__,9)) ;
		
		
		// 获取 所有的静态方法
		if( $Methods==='*' )
		{
			$Methods = array() ;
			$arrAllMethods = get_class_methods($sClass) ;
			foreach($arrAllMethods as $sMethod)
			{
				$aRef = new ReflectionMethod($sClass,$sMethod) ;
				if( !$aRef->isStatic() )
					continue ;
				$Methods[] = $sMethod ;
			}
		}
		
		// 检查参数类型
		if( !is_array($Methods) )
			throw new JCAT_Exception("参数 $Methods 非法。",JCAT_Exception::MakeExceptionCode(__CLASS__,6)) ;
		
		// 创建 与方法 同名的全局函数
		$nCount = 0 ;
		foreach($Methods as $sMethod)
		{
			JCAT_Global::MakeFunctionAlias($sMethod,array($sClass,$sMethod)) ;
			$nCount ++ ;
		}
		
		return $nCount ;
	}

	
	/**
	 * 从一个 实例文件 导入实例
	 *
	 * @access	public
	 * @param	$sInstanceFile	string	实例文件路径
	 * @static
	 * @return	object
	 */
	static public function ImportInstance( $sInstanceNameOrFile, $DirOrPackageID=null /*...*/ )
	{
		// 直接指定 实例文件
		if( is_file($sInstanceNameOrFile) )
		{
			$sInstanceFilePath = $sInstanceNameOrFile ;
		}
		
		// 通过实例名称 和 所在目录定位实例文件
		else
		{
			// 包 所在目录
			if( is_int($DirOrPackageID) )
			{
				$sDir = self::GetPackagePath($DirOrPackageID) ;
			}
			else if( is_dir($DirOrPackageID) )
			{
				$sDir = $DirOrPackageID ;
			}
			else 
			{
				JCAT_ASSERT::ASSERT_(0,JCAT_Language::SentenceEx("参数\$DirOrPackageID({%s})无效。",'JCAT',null,$DirOrPackageID));
			}
				
			// 按照命名规则寻找类文件
			$sInstanceFilePath = self::FindClassFileByNamingRule($sInstanceNameOrFile,$sDir,self::$arrInstanceFilePatterns) ;
			
		}
		
		JCAT_ASSERT::ASSERT_FILE($sInstanceFilePath,"Coundn`t found Instance {$sInstanceNameOrFile}`s file and imported it. ") ;

		// 创建实例所需 参数
		$arrArgs = func_get_args() ;
		array_shift($arrArgs) ;
		array_shift($arrArgs) ;
		
		// 载入实例文件
		$aNewIns = @include $sInstanceFilePath ;
		
		// 检查返回值
		if( !is_object($aNewIns) )
		{
			throw new JCAT_Exception( JCAT_Language::SentenceEx('实例文件中必须通过 return 明文返回一个对象。','JCAT',null), __macro_exception_code__ ) ;
		}

		return $aNewIns ;
	}
	


	/**
	 * 通过包的ID 得到完整路径
	 * 
	 * @access	public
	 * @param	$nPackageID	int		包的ID， JCAT 的一个代表包的类常量
	 * @static
	 * @return	string,null
	 */
	static public function GetPackagePath( $nPackageID )
	{
		if( isset(self::$arrPackagesPath[$nPackageID]) )
		{
			return JCATPATH . self::$arrPackagesPath[$nPackageID] ;
		}
		else
		{
			return null ;
		}
	}


	/**
	 * 给入一个类（或接口）的名称，按照 JCAT 的文件命名规则 到指定的目录中 寻找该类（或接口）的文件
	 * 
	 * @access	public
	 * @param	$Dirs				string,array	指定的目录，可以是 array （多个目录）,或 string （单个目录）
	 * @param	$sClassName			string			类（或接口）名称
	 * @param	$bInterface=false	bool			是否是一个接口
	 * @static
	 * @return	string,false						如果没有找到，返回 false
	 */
	static public function FindClassFileByNamingRule($sClassName,$Dirs=null,$arrPatterns=null)
	{
		if( $Dirs===null )
		{
			$arrDirs = self::$arrImportedPackageDir ;	
		}
		else if( is_string($Dirs) )
		{
			$arrDirs = array($Dirs) ;
		}
		else if( is_array($Dirs) )
		{
			$arrDirs = $Dirs ;
		}
			
		if( !is_array($arrDirs) )
		{
			throw new JCAT_Exception('参数 $Dirs 必须为数组或字符串。',JCAT_Exception::MakeExceptionCode(__CLASS__,11)) ;
		}
		
		if( $arrPatterns===null )
		{
			$arrPatterns = self::$arrClassFilePatterns ;
		}
		JCAT_ASSERT::ASSERT_ISTHESE($arrPatterns,array('array:string')) ;
		
		foreach($arrDirs as $sDir)
		{
			$sDir = JCAT_Global::TidyPath($sDir) ;
		
			foreach($arrPatterns as $sPattren)
			{
				$sPath = str_replace('%ClassName%',$sClassName,$sPattren) ;
				$sPath = str_replace('%DirPath%',$sDir,$sPath) ;
				
				$bFindout = is_file($sPath) ;
				if( $bFindout )
					return $sPath ;
			}
		}
		
		return false ;
	}

	
	/**
	 * 注册 类-类文件
	 * 
	 * @access	public
	 * @param	$sClass			string		what's this
	 * @param	$sPath			string		what's this
	 * @return	void
	 * @static
	 */
	static public function RegisterClass($sClass,$sPath)
	{
		if( !is_string($sClass) )
		{
			exit( JCAT_Language::SentenceEx('参数 $sClass 必须是一个字符串格式的类名','JCAT',null) ) ;
		}
		
		// 高频度使用 is_file() 会占用过高 cpu ，将判断延迟到 autoload 中，可有效减少不必要的 is_file 访问
		//if( !is_file($sPath) )
		//{
		//	exit( JCAT_Language::SentenceEx('参数 $sPath( %s ) 必须是一个存在的文件','JCAT',null,$sPath) ) ;
		//}

		if( isset(self::$arrClassesPath[$sClass]) )
		{
			exit( JCAT_Language::SentenceEx('类%s已经存在于：%s，无法重复注册（%s）。','JCAT',null,$sClass,self::$arrClassesPath[$sClass],$sPath) ) ;
		}

		self::$arrClassesPath[$sClass] = $sPath ;
	}
	
	/**
	 * 为已经注册的类创建一个迭代器
	 *
	 * @access	public
	 * @return	JCAT_IIterator
	 */
	public function CreateClassIterator()
	{
		return new JCAT_ArrayIterator(self::$arrClassesPath) ;
	}
	
	/**
	 * 注册一个Class 到指定包中。返回 类 的 全局唯一ID
	 * 
	 * @access	public
	 * @param	$sClassName				string	类名
	 * @param	$nPackageID				int		包 ID
	 * @param	$nClassIDInPackage		int		类在 包中的 ID
	 * @static
	 * @return	int
	 */
	static public function RegisterClassID( $sClassName, $nPackageID, $nClassIDInPackage )
	{
		$nClassID = ($nPackageID<<8)|$nClassIDInPackage ;
		
		// 定义常量
		if( !defined($sClassName) )
		{
			define($sClassName,$nClassID) ;			
		}
			
		if( isset(self::$arrClassIDs[$nClassID]) )
		{
			throw new JCAT_Exception(
				JCAT_Language::SentenceEx('同一个 Class 只能注册一个类，ID：“{%d}”已经注册为：“{%s}”','JCAT',null,$nClassID,self::$arrClassIDs[$nClassID])
				,JCAT_Exception::MakeExceptionCode(__CLASS__,12)
			) ;
		}
		
		self::$arrClassIDs[$nClassID] = $sClassName ; 
	}
	
	/**
	 * 根据一个 Class ID 查询类名
	 * 
	 * @access	public
	 * @param	$nClassID	int	Class ID
	 * @static
	 * @return	string,null
	 */
	static public function GetClassByID($nClassID)
	{ return self::$arrClassIDs[$nClassID] ; }
	
	
	/**
	 * 返回指定类 所属的包 的ID。  所指定的类必须已经通过JCAT_Package::RegisterClassID()  注册，如果没有注册，返回 0
	 * 
	 * @access	public
	 * @param	$sClassName	string	类名称
	 * @static
	 * @return	int
	 */
	static public function GetPackageIDByClass($sClassName)
	{
		if( !defined($sClassName) )
		{
			return 0 ;
		}

		$nClassID = constant($sClassName) ;
		
		if( !isset(self::$arrClassIDs[$nClassID]) )
		{
			return 0 ;
		}

		return ($nClassID>>8) ;
	}


	/**
	 * 自动加载 类/接口 文件 开关
	 * 
	 * @access	public
	 * @param	$bAutoload=true		bool		是否自动加载
	 * @return	old_value
	 */
	static public function SetAutoload($bIsAutoload)
	{
		if( !is_bool($bIsAutoload) )
		{
			$bAutoload = $bIsAutoload? true: false ;
		}
		else
		{
			$bAutoload = $bIsAutoload ;
		}
		
		$old_value = self::$bAutoload ;
		self::$bAutoload = $bAutoload ;
		return $old_value ;
	}

	/**
	 * 自动加载 类/接口 文件 状态
	 * 
	 * @access	public
	 * @return	bool
	 */
	static public function GetAutoload()
	{
		return self::$bAutoload ;
	}
	
	/**
	 * 在执行 php 原生函数 class_exists() 或  interface_exists()  的时候，如果存在符合 文件命名规则的类(接口)文件，JCAT框架 会自动 加载。
	 * 此方法 JCAT_Package::ClassExists() 效果等同，但是提供 是否自动加载的 选择。
	 * 
	 * @access	public
	 * @param	$sClassOrInterfaceName		string			类 或 接口名称
	 * @param	$bInterface=false			bool			指示 参数 $sClassOrInterfaceName 是否是一个接口
	 * @param	$bAutoloadIfFind=false		string			如果依据 文件命名规则 找到 类文件，是否自动加载
	 * @return	bool
	 */
	static public function ClassExists($sClassOrInterfaceName,$bInterface=false,$bAutoloadIfFind=false)
	{
		$bAutoloadOldValue = self::SetAutoload($bAutoloadIfFind) ;
		
		$sFuncName = $bInterface? 'interface_exists': 'class_exists' ;
		$bRet = $sFuncName($sClassOrInterfaceName) ;
		
		self::SetAutoload($bAutoloadOldValue) ;
		return $bRet ;
	}
	
	/**
	 * __autoload 的实际处理函数
	 * 
	 * @access	public
	 * @param	$sClassOrInterface		string	正在载入的 类名 或 接口名
	 * @static
	 * @return	void
	 */
	static public function OnAutoLoad( $sClassOrInterface ) 
	{
		if( !self::$bAutoload )
		{
			return ;
		}

		if( array_key_exists($sClassOrInterface,self::$arrClassesPath) )
		{
			// for debug 
			if( self::$bSaveLoadTime )
			{
				$nStartTime = microtime(true) ;
				self::$bSaveLoadTime = false ;			// 避免因嵌套 include 而重复累加时间
				
				require self::$arrClassesPath[$sClassOrInterface] ;
				
				self::$arrClassLoadTimes[$sClassOrInterface] = microtime(true)-$nStartTime ;
				self::$bSaveLoadTime = true ;
			}
			
			// for release
			else 
			{
				if( !is_file(self::$arrClassesPath[$sClassOrInterface]) )
				{
					exit( JCAT_Language::SentenceEx('无法载入类：%s 所在的文件：  %s','JCAT',null,$sClassOrInterface,self::$arrClassesPath[$sClassOrInterface]) ) ;
				}
				require self::$arrClassesPath[$sClassOrInterface] ;
			}
		}
	}	
	
	/**
	 * 在 __sleep() 魔术函数中，如果直接返回一个 private 属性的名称，则对 子类对象 serialize 操作时 无效。
	 * 此函数 返回一个 任何时候 都有效的  属性名称。
	 * 
	 * @access	public
	 * @param	$sPropertyName		string	属性名称
	 * @param	$sClassName			string	正在载入的 类名 或 接口名
	 * @static
	 * @return	void
	 */
	static public function MakePrivatePropertyNameForSerialize( $sPropertyName, $sClassName )
	{
		JCAT_ASSERT::ASSERT_STRING($sPropertyName);
		JCAT_ASSERT::ASSERT_STRING($sClassName);
		
		return chr(0).$sClassName.chr(0).$sPropertyName ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sPropertyName
	 * @static
	 * @return	string
	 */
	static public function MakePropertyPropertyNameForSerialize($sPropertyName)
	{
		JCAT_ASSERT::ASSERT_STRING($sPropertyName);
		return "\0*\0".$sPropertyName ;
	}

	/**
	 * 扫描目录下的类
	 * 
	 * @access	private
	 * @param	$sDirectory			string		what's this
	 * @return	array
	 */
	static private function ScanClass($sDirectory,$sPreFilename='')
	{
		JCAT_ASSERT::ASSERT_DIR($sDirectory) ;
		$arrReturnClasses = array() ;
		
		// 整理 路径为统一格式
		$sDirectoryPath = realpath($sDirectory).'/' ;

		// 
		$hDir = opendir($sDirectoryPath) ;
		JCAT_ASSERT::ASSERT_($hDir) ;
		
		while( $sFilename=readdir($hDir) )
		{
			$sPath = $sDirectoryPath.$sFilename ;
			
			// 文件
			if(is_file($sPath))
			{
				foreach (self::$arrClassFileRegexpPatterns as $sRegexp)
				{
					// 找到 类文件
					$arrRes = array() ;
					if( preg_match($sRegexp,$sFilename,$arrRes) )
					{
						$sClassName = isset($arrRes[1])? $arrRes[1]: null ;
						if($sClassName)
						{
							$arrReturnClasses[] = array(
								'class' => $sClassName ,
								'file' => $sPreFilename.$sFilename 
							);
						}
					}
				}
			}
			
			// 目录
			else if( is_dir($sPath) )
			{
				// 排除特殊目录
				if(in_array($sFilename,array('.','..','.svn')))
				{
					continue ;
				}
				
				// 递归子目录
				else
				{
					$arrReturnClasses = array_merge(
						$arrReturnClasses,
						self::ScanClass($sPath,$sPreFilename.$sFilename.'/')
					);
				}
			}
			
			else
			{
				JCAT_ASSERT::ASSERT_(0,"what's this: {$sPath} ?")  ;
			}
		}
		
		return $arrReturnClasses ;
	}
	
	
	/**
	 * 查询一个静态方法 是否在 HTTP 上公开
	 * 
	 * @access	public
	 * @param	$sMethodName	string	What's this Parameter ?
	 * @return	void
	 */
	static public function IsPublicOnHTTP( $sMethodName )
	{
		return in_array( strtolower($sMethodName), array(
			'importjspackage'
			, 'importjsclass' ) ) ;
	}
	
	
	/**
	 *  为客户端引入一个 JS包
	 * 
	 * @access	public
	 * @param	$sPackage			string		what's this
	 * @param	$bFromClient=true	bool		what's this
	 * @param	$bRePack=false		bool		what's this
	 * @return	void
	 */
	static public function ImportJSPackage($sPackage,$bFromClient=true,$bRePack=false)
	{
		// 项目状态： 不使用缓存
		if( JCAT_ProjectState::Get(JCAT_ProjectState::NO_CACHE) )
		{
			$bRePack = true ;
		}
		
		$sPackagePath = str_replace('.','/',$sPackage) ;
		$sFSPath = preg_replace('/^JCAT/',JCATPATH.'Lib.js',$sPackagePath) ;
		$sPackagePath = $sFSPath.'/package.'.basename($sPackagePath).'.js' ;
		
		if( !is_dir($sFSPath) )
		{
			return ;
		}
		
		// 打包
		if( $bRePack or !is_file($sPackagePath) )
		{
			self::PackupJS($sFSPath,$sPackagePath);
		}
		
		if(!is_file($sPackagePath))
		{
			return ;
		}
		
		// 来自 Client 的下载请求
		if($bFromClient)
		{
			JCAT_DownloadFile::Download($sPackagePath) ;
		}
		
		// 来自 PHP 引用
		else
		{
			JCAT_HTMLResourceContainer::PutInResource(new JCAT_JS($sPackagePath)) ;			
		}
	}
	
	
	
	/**
	 *  将一个 JS 文件目录整个打包
	 * 
	 * @access	private
	 * @param	$sDir			string		what's this
	 * @return	void
	 */
	static private function PackupJS($sDir,$sPackagePath)
	{
		$sPackOrderFile = $sDir.'/pack.order' ;
		if(is_file($sPackOrderFile))
		{
			$sPackOrder = file_get_contents($sPackOrderFile) ;
			$sPackOrder = str_replace("\r",'',$sPackOrder) ;
			$arrPackOrder = explode("\n",$sPackOrder) ;
		}
		else 
		{
			$arrPackOrder = array() ;
		}
				
		// 开始历遍包内的文件
		$aIterator = new JCAT_FSOIterator($sDir) ;
		$aIterator->First() ;
		while( !$aIterator->IsDone() )
		{
			$sFileName = $aIterator->Current() ;
			
			if( !in_array($sFileName,$arrPackOrder) )
			{
				if( preg_match('/^(class|interface)\..+\.js$/i',$sFileName) )
				{
					$arrPackOrder[] = $sFileName ;
				}
			}
			
			$aIterator->Next() ;
		}
		
		// 打包
		$hPackage = fopen($sPackagePath,'w') ;
		chmod($sPackagePath,0666) ;
		foreach($arrPackOrder as $sFileName)
		{
			if(!$sFileName)
			{
				continue ;
			}
			$sFilePath = $sDir.'/'.$sFileName ;
			fwrite($hPackage,
				JCAT_Language::SentenceEx("\r\n// JS 文件: %s \r\n"
					,'JCAT',null,$sFilePath)
			) ;
			fwrite($hPackage,"// ----------------------------------------------------------------------------------------\r\n") ;
			
			if( is_file($sFilePath) )
			{
				fwrite($hPackage,file_get_contents($sFilePath)) ;
			}
			
			else 
			{
				fwrite($hPackage,JCAT_Language::SentenceEx("throw new Error('丢失JS文件:%s!') ;",'JCAT',null,$sFilePath)) ;
			}
			
			fwrite($hPackage,str_repeat("\r\n",4)) ;
		}
		
		fclose($hPackage) ;
	}
	
	
	/**
	 *  为客户端引入一个 JS类
	 * 
	 * @access	public
	 * @param	$sClassName			string		what's this
	 * @static
	 * @return	void
	 */
	static public function ImportJSClass($sClassName)
	{
		$sClassPath = '' ;
		$arrElements = explode('.',$sClassName) ;
		$sFileTitle = array_pop($arrElements) ;
		$nDepth = count($arrElements) ;
		if($nDepth>2)
		{
			for( $i=1; $i<$nDepth; $i++ )
			{
				$sClassPath.= $arrElements[$i].'/' ;
			}
		}
		
		$sClassPath =  JCATPATH."Lib.js/{$sClassPath}class.{$sFileTitle}.js" ;
		
		JCAT_DownloadFile::Download($sClassPath);
	}
	
	
	/**
	 * 添加一个用于查找类文件的 正则表达式
	 *
	 * @access	public
	 * @param 	$sRegExp
	 * @static
	 * @return	void
	 */
	static public function AddClassNamePattern($sRegExp)
	{
		self::$arrClassFileRegexpPatterns[] = $sRegExp ;
	}
	
	/**
	 * 设置 ClassesPath 文件名
	 *
	 * @access	public
	 * @param 	$sFilename
	 * @static
	 * @return	old_value
	 */
	static public function SetClassesPathFilename($sFilename)
	{
		$old_value = self::$sClassesPathFilename ;
		self::$sClassesPathFilename = $sFilename ;
		return $old_value ;
	}
	
	// 属性 ///////////////////////////////////////////////////////////////////////////////

	/**
	 * 类 和 类文件路径 映射表
	 * 
	 * @access	private
	 * @var		array
	 * @static
	 */
	static private $arrClassesPath ;
	
	/**
	 * 
	 * 
	 * @access	private
	 * @var		array
	 * @static
	 */
	static public $arrClassLoadTimes ;
	
	static public $bSaveLoadTime = false ;
	
	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 * @static
	 */
	static private $arrImportedPackageDir = array() ;

	static private $sClassesPathFilename = 'inc.ClassesPath.php' ;
	
	/**
	 * 对照表：包ID => 包相对路径
	 * 
	 * @access	private
	 * @var		
	 * @static
	 */
	static private $arrPackagesPath = array(
		JCAT::PACKAGE_LIBPHP => 'Lib.php/' ,
		JCAT::PACKAGE_APP => 'Lib.php/Application/' ,
		JCAT::PACKAGE_COMMON => 'Lib.php/Common/' ,
		JCAT::PACKAGE_MVC => 'Lib.php/MVC/' ,
		JCAT::PACKAGE_ADVANCE => 'Lib.php/Advance/' ,
		JCAT::PACKAGE_BACKTRACE => 'Lib.php/Application/Backtrace/' ,
		JCAT::PACKAGE_DEBUG => 'Lib.php/Advance/Debug/' ,
		JCAT::PACKAGE_LANG => 'Lib.php/Application/Language/' ,
		JCAT::PACKAGE_PATTERN => 'Lib.php/Application/Pattern/' ,
		JCAT::PACKAGE_REQUEST => 'Lib.php/Application/Request/' ,
		JCAT::PACKAGE_DATASTRUCT => 'Lib.php/Common/DataStruct/' ,
		JCAT::PACKAGE_FS => 'Lib.php/Common/FileSystem/' ,
		JCAT::PACKAGE_DB => 'Lib.php/Common/DB/' ,
		JCAT::PACKAGE_UI => 'Lib.php/Common/UI/' ,
		JCAT::PACKAGE_DBFACTORY => 'Lib.php/Common/DB/DBFactory/' ,
		JCAT::PACKAGE_DBOBJECT => 'Lib.php/Common/DB/DBObject/' ,
		JCAT::PACKAGE_DBCONNECT => 'Lib.php/Common/DB/DBConnect/' ,
		JCAT::PACKAGE_DBSQL => 'Lib.php/Common/DB/DBSQL/' ,
		JCAT::PACKAGE_DBRECORDSET => 'Lib.php/Common/DB/DBRecordSet/' ,
		JCAT::PACKAGE_DBSUBSQL => 'Lib.php/Common/DB/DBSQL/DBSubSQL/' ,
		JCAT::PACKAGE_UIGTK => 'Lib.php/Common/UI/UIGtk/' ,
		JCAT::PACKAGE_UIHTML => 'Lib.php/Common/UI/UIHtml/' ,
		JCAT::PACKAGE_UIHTMLPARSER => 'Lib.php/Common/UI/UIHtml/Parser/' ,
		JCAT::PACKAGE_UIHTMLCOMPILER => 'Lib.php/Common/UI/UIHtml/Compiler/' ,
		JCAT::PACKAGE_UIHTMLCODECOMPILER => 'Lib.php/Common/UI/UIHtml/Compiler/CodeCompiler/' ,
		JCAT::PACKAGE_UIHTMLNODECOMPILER => 'Lib.php/Common/UI/UIHtml/Compiler/NodeCompiler/' ,
		JCAT::PACKAGE_CACHE => 'Lib.php/Common/Cache/' ,
		JCAT::PACKAGE_UIGTKCOMPILER => 'Lib.php/Common/UI/UIGtk/UIGtkGladeWidgetCompiler/' ,
		
		JCAT::PACKAGE_MVCGTK => 'Lib.php/MVC/MVCGtk/' ,
		JCAT::PACKAGE_MVCHTML => 'Lib.php/MVC/MVCHtml/' ,
		JCAT::PACKAGE_MVCDV => 'Lib.php/MVC/DataVerifier/' ,
		JCAT::PACKAGE_DOC => 'Lib.php/MVC/Model/' ,
		JCAT::PACKAGE_UICTRLGTK => 'Lib.php/MVC/MVCGtk/UICtrlGtk/' ,
		JCAT::PACKAGE_UICTRLHTML => 'Lib.php/MVC/MVCHtml/UIHtmlCtrl/' ,
		JCAT::PACKAGE_UICTRLHTMLBASE => 'Lib.php/MVC/MVCHtml/UIHtmlCtrl/' ,
		JCAT::PACKAGE_UICTRLHTML => 'Lib.php/MVC/MVCHtml/UIHtmlCtrl/' ,
		JCAT::PACKAGE_UICTRLHTMLBASE => 'Lib.php/MVC/MVCHtml/UIHtmlCtrl/Base/' ,
		JCAT::PACKAGE_UICTRLHTMLADV => 'Lib.php/MVC/MVCHtml/UIHtmlCtrl/Advance/' ,
		
		JCAT::PACKAGE_MSG => 'Lib.php/Common/Message/' ,


	) ;

	/**
	 * 对照表：已注册的 Class ID=>Class Name
	 * 
	 * @access	private
	 * @var		array
	 * @static
	 */
	static private $arrClassIDs = array() ;
	
	
	/**
	 * 自动加载
	 * 
	 * @access	private
	 * @var		bool
	 * @static
	 */
	static private $bAutoload = true ;
	
	static private $arrClassFileRegexpPatterns = array(
			'/^class\.(.+)\.php$/i'
			, '/^interface\.(.+)\.php$/i'
	) ;
	
	static private $arrClassFilePatterns = array(
			'%DirPath%class.%ClassName%.php' ,
			'%DirPath%classes.%ClassName%.php' ,
			'%DirPath%%ClassName%.class.php' ,
			'%DirPath%%ClassName%.classes.php' ,
			'%DirPath%%ClassName%.php' ,
	) ;
	
	static private $arrInterfaceFilePatterns = array(
			'%DirPath%interface.%ClassName%.php' ,
			'%DirPath%interfaces.%ClassName%.php' ,
			'%DirPath%%ClassName%.interface.php' ,
			'%DirPath%%ClassName%.interfaces.php' ,
			'%DirPath%%ClassName%.php' ,
	) ;
	
	static private $arrInstanceFilePatterns = array(
			'%DirPath%instance.%ClassName%.php' ,
			'%DirPath%%ClassName%.instance.php' ,
			'%DirPath%ins.%ClassName%.php' ,
			'%DirPath%%ClassName%.ins.php' ,
			'%DirPath%%ClassName%.php' ,
	) ;
	
	
}


/*macro_exception_code:12*/
?>